#ifndef GENE_HH
#define GENE_HH

#include <iosfwd>
#include "mutations.hh"
#include "node_type.hh"

namespace evolution {

    class Gene {
        float weight = 0;

    public:
        Gene (float weight);

        float get_weight() const { return weight; }
       
        static float random_weight ();

        virtual bool mutate ();
        virtual ~Gene () { }
    };

    class NodeGene : public Gene {
        NodeType type;
        int id;

    public:
        NodeGene(int id, float bias, NodeType type);

        NodeType get_type() const { return type; }
        int get_id() const { return id; } 

        static NodeType random_type();

        friend std::ostream& operator << (std::ostream& out, NodeGene const&);

        virtual bool mutate();
    };

    class ConnectionGene : public Gene {
        int innovation_number;
        bool enabled;

        static int INNOVATION;

        int source;
        int target;

    public:
        ConnectionGene(int innovation_number, int source, int target, float weight, bool enabled);
        
        int get_innovation_number() const { return innovation_number; }
        int get_source() const { return source; }
        int get_target() const { return target; }

        void set_enabled(bool enabled) { this->enabled = enabled; }
        bool get_enabled() const { return enabled; }


        static int new_innovation_number ();

        friend std::ostream& operator << (std::ostream&, ConnectionGene const&);

        virtual bool mutate();
    };

}

#endif
